# 13. XSS、CSRF区别
# 1. XSS
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。实现xss攻击具备2个条件,第一需要向web页面注入恶意的代码,第二,这些恶意代码被浏览器成功的执行。
# 攻击类型
根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。
存储型
- 攻击者将恶意代码提交到目标网站的数据库中。
- 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
- 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
反射型 XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
- 反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。
POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。
DOM 型 XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL。
- 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
# 预防
XSS 攻击有两大要素:
- 攻击者提交恶意代码。
- 浏览器执行恶意代码。
如果是前端过滤的,攻击者直接绕过前端发送请求就可以提交恶意代码了。
如果是后端插入数据库前过滤的,则并不知道内容输出到哪里,不同位置编码可能会不同,可能会造成乱码问题。
所以输入过滤并不可靠。
预防存储型和反射型XSS攻击有两种常见做法:
- 改成纯前端渲染,把代码和数据分隔开。
- 对HTML做转义
& < > " ' /
预防 DOM 型 XSS 攻击
DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。
在使用 .innerHTML、.outerHTML、document.write() 时要特别小心。eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。
启用CSP。
# XSS 的检测
- 手动利用XSS攻击字符串进行检测。
- 利用XSS漏洞扫描工具进行扫描。

# 2. CSRF
你向同一个服务器发请求时会带上浏览器保存的对于那个服务器的cookie,而不管你从哪个网站发请求。
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
一个典型的CSRF攻击有着如下的流程:
- 受害者登录a.com,并保留了登录凭证(Cookie)。
- 攻击者引诱受害者访问了b.com。
- b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
- a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
- a.com以受害者的名义执行了act=xx。
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
# 攻击类型
- GET类型的CSRF:访问含有img的页面自动发送GET请求。
- POST类型的CSRF:自动提交表单。
- 链接类型的CSRF:比如论坛中发布的图片嵌入链接,用户点击就会将认证信息带过去。
# 预防
CSRF(通常)发生在第三方域名。
CSRF攻击者不能获取到Cookie等信息,只是使用。攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。
CSRF自动防御策略:同源检测(Origin 和 Referer 验证)。
CSRF主动防御措施:Token验证(利用了CSRF无法获取到Cookie信息) 或者 双重Cookie验证(两个sessionid,请求时将一个拼接到url后面,后台比较url参数和另一个session是否相等,利用了CSRF无法获取到Cookie信息) 以及配合Samesite Cookie。
保证页面的幂等性,后端接口不要在GET页面中做用户操作。
# 3. CSRF和XSS的区别
- CSRF需要登录,冒用COOKIE,利用网站本身的漏洞,去请求网站的api
- XSS,不需要登录,向网站注入JS代码,执行JS里的代码,篡改网站的内容
# 4. 参考
前端安全系列(一):如何防止XSS攻击? (opens new window) 前端安全系列之二:如何防止CSRF攻击? (opens new window)
| 攻击方式 | 一句话概括 | 攻击目标 | 攻击方向 |
|---|---|---|---|
| XSS(跨站脚本攻击) | “你在我的页面里执行了恶意代码” | 用户(窃取用户数据) | 攻击者 → 用户 |
| CSRF(跨站请求伪造) | “你借用我的身份去执行了操作” | 网站(冒充用户操作) | 用户 → 网站(被利用) |
# 二、XSS(跨站脚本攻击)
# 核心原理
XSS 是指攻击者往网页中注入恶意脚本,当用户浏览该页面时,脚本就会在用户浏览器中执行。
攻击流程:
1. 攻击者在评论区提交恶意脚本
<script>document.cookie</script>
2. 服务器没有过滤,存储到了数据库
3. 正常用户访问页面,浏览器执行该脚本
→ 攻击者窃取了用户的 Cookie/Token
2
3
4
5
6
7
# 攻击类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 反射型 XSS | 恶意脚本通过 URL 参数传递,后端直接输出到页面 | https://site.com/search?q=<script>alert(1)</script> |
| 存储型 XSS | 恶意脚本存储在服务器(如评论区、留言板),访问时执行 | 在评论区提交 <script>fetch('/api/user')</script> |
| DOM 型 XSS | 恶意脚本通过修改 DOM 结构触发,不经过服务器 | 从 URL 取参数,用 innerHTML 渲染 |
# 防御方案
// ✅ 1. 输出时转义(最重要!)
function escapeHtml(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
// ✅ 2. 不使用 innerHTML,用 textContent
element.textContent = userInput // ✅ 安全
element.innerHTML = userInput // ❌ 危险
// ✅ 3. HTTP-only Cookie
// 设置 Cookie 时加 HttpOnly 属性,禁止 JS 读取
Set-Cookie: sessionId=xxx; HttpOnly; Secure
// ✅ 4. CSP(内容安全策略)
// 限制只允许加载同源脚本
Content-Security-Policy: script-src 'self'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 三、CSRF(跨站请求伪造)
# 核心原理
CSRF 是指攻击者利用用户已经登录的身份,在用户不知情的情况下,诱导用户发送恶意请求。
攻击流程:
1. 用户登录了银行网站 A,Cookie 未过期
2. 攻击者在恶意网站 B 中嵌入:
<img src="https://bank.com/transfer?to=attacker&amount=1000">
3. 用户访问网站 B,浏览器自动带上 A 的 Cookie
4. 银行服务器收到请求,以为用户本人操作 → 转账成功
2
3
4
5
# 关键条件
✅ 用户已登录目标网站(Cookie 有效)
✅ 目标网站的 Cookie 没有 SameSite 限制
✅ 攻击者能预测请求的 URL 和参数(GET 型)或诱导用户提交表单(POST 型)
2
3
# 防御方案
// ✅ 1. CSRF Token(最常用)
// 在表单中埋入随机 Token,服务器验证
<form>
<input type="hidden" name="csrf_token" value="随机字符串">
<input type="text" name="amount">
<button>转账</button>
</form>
// ✅ 2. SameSite Cookie(推荐!)
// 设置 Cookie 的 SameSite 属性
Set-Cookie: sessionId=xxx; SameSite=Strict
// Strict:只有同源请求才携带 Cookie
// Lax:只允许 GET 导航到目标地址时携带
// ✅ 3. 验证 Referer 头
// 服务器检查请求来源是否为同源
// ✅ 4. 关键操作使用 POST,配合 CSRF Token
// GET 请求容易被 img 标签等跨站发起
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 四、XSS vs CSRF 核心对比
| 对比维度 | XSS | CSRF |
|---|---|---|
| 攻击者目标 | 窃取用户数据(Cookie、Token、个人信息) | 冒充用户执行操作(转账、发消息、修改密码) |
| 攻击方式 | 向页面注入恶意脚本 | 诱导用户发起请求(利用已登录状态) |
| 受害者 | 浏览器使用者(脚本在用户浏览器执行) | 网站服务器(请求是从用户浏览器发出) |
| 是否需要用户执行 | 用户访问页面即可触发 | 用户点击链接或访问恶意网站 |
| 防御重点 | 输入过滤 + 输出转义 | 请求来源验证 + Token + SameSite |
# 一句话区别
XSS 是代码注入攻击,攻击者直接在你的页面里执行恶意脚本;CSRF 是身份冒用攻击,攻击者利用你的身份,在你不操作时替你发请求。
# 五、面试回答话术
XSS 和 CSRF 是 Web 安全中最常见的两种攻击方式,它们的区别体现在三个方面:
1. 攻击目标不同
- XSS 攻击的是用户,目的是窃取用户的数据(Cookie、Token、个人信息)
- CSRF 攻击的是网站,目的是冒充用户执行非法操作(转账、删数据)
2. 攻击方式不同
- XSS 通过注入恶意脚本到页面,用户访问时自动执行
- CSRF 通过诱导用户发送请求,利用已登录的身份
3. 防御方向不同
- 防御 XSS 靠的是输入验证 + 输出转义,以及设置 HttpOnly Cookie
- 防御 CSRF 靠的是CSRF Token、SameSite Cookie、验证 Referer 头
两者也有关系:如果一个网站有 XSS 漏洞,攻击者可以利用 XSS 窃取到 CSRF Token,从而绕过 CSRF 防御。所以先防 XSS,再防 CSRF,是安全防御的基本顺序。
# 六、实际防御示例
# 在 Vue 项目中的防御
// 1. Vue 模板中的 XSS 防御
// Vue 默认会对 {{ }} 中的内容进行转义,防止 XSS
<div>{{ userInput }}</div> // ✅ 安全,Vue 自动转义
// ❌ 危险:使用 v-html 时需确保内容可信
<div v-html="trustedHtml"></div> // ⚠️ 只有可信内容才用
// 2. 接口请求携带 CSRF Token
// axios 拦截器
axios.interceptors.request.use(config => {
// 从 Cookie 或 meta 标签读取 CSRF Token
const token = document.querySelector('meta[name="csrf-token"]').content
config.headers['X-CSRF-Token'] = token
return config
})
// 3. 设置 Cookie 的属性(服务端)
// httpOnly: 禁止 JS 读取
// SameSite: 限制跨站请求携带 Cookie
// Secure: 仅 HTTPS 传输
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 七、记忆口诀
XSS → 脚本注入偷数据
CSRF → 身份冒用搞破坏
防 XSS:转义 + HttpOnly + CSP
防 CSRF:Token + SameSite + Referer
先防 XSS,再防 CSRF!
2
3
4
5
6
7